#include <msp430.h> 
#include "softuart.h"
#include "def.h"
#include "epd.h"
#include "softspi3w.h"
#include "common.h"
#include "font.h"




typedef struct 
{
    uint8_t sta;
    uint8_t mode;
}t_clock_disp_update;

void InitClk(void);
void InitGpio(void);
uint8_t uart_callback(void *d, uint8_t sta, uint8_t rx);


//static uint8_t rxbuf[10];
//static uint8_t rxidx=0;

//static const uint8_t c_Test[]= {0xFF};


uint8_t LPM3Prohibit = 0;
t_EPD_InitUpdate m_EPD_InitUpdate = {0xFF};
t_clock_disp_update m_ClockDispUpdate = {0xFF};

void clock_disp(uint8_t mode);
void clock_disp_start(t_clock_disp_update *d, uint8_t mode);
void clock_disp_update(t_clock_disp_update *d);
void LPM3_Process(void);

void printtest(uint8_t x, uint8_t y, uint8_t const *str)
{
    uint8_t const *p = str;
    uint8_t ytmp = y;
    while(*p != '\0')
    {
        EPD_DrawPic(x,ytmp,8,5, nAsciiDot5x8[*p-' ']);
        ytmp += 6;
        p++;
    }
    EPD_Disp(EPD_PART);
    EPD_WaitBusy();
    p = str;
    ytmp = y;
    while(*p != '\0')
    {
        EPD_DrawPic(x,ytmp,8,5, nAsciiDot5x8[*p-' ']);
        ytmp += 6;
        p++;
    }
}

/**
 * main.c
 */
int main(void)
{
	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
	InitClk();
	InitGpio();
    
	__enable_interrupt();

    SWUART_Init();

    // Init EDP power and SPI
    EPD_POW_ON();
    DelayMs(200);
    EPD_CS_HIGH();
    SWSPI3W_IOInit();
    DelayMs(10);


    P2IE |= TIMER_1S; // Enable TIMER_1S interrupt. 

    // Start EDP 
    clock_disp_start(&m_ClockDispUpdate, EPD_FULL);

	for(;;)
	{
        EPD_BusyUpdate();

        EPD_InitUpdate(&m_EPD_InitUpdate);
        clock_disp_update(&m_ClockDispUpdate);

	}
}

void InitClk(void)
{
  BCSCTL1 = CALBC1_16MHZ;                    // Set range
  DCOCTL = CALDCO_16MHZ;

  BCSCTL3 = LFXT1S_2;                   /* Mode 2 for VLOCLK :*/
  while (BCSCTL3 & LFXT1OF);
  IFG1 &= ~(OFIFG);
}

void InitGpio(void)
{
    P1OUT = 0x00;               //
    P1SEL = FLASH_CK | FLASH_SI | FLASH_SO;               // 
    P1SEL2 = FLASH_CK | FLASH_SI | FLASH_SO;
    P1DIR = 0xFF | ~FLASH_SO;               // Set all pins to output
    

    P2OUT = RF_POW | SWUART_RXD;   // RF_POW off, SWUART pull up resistor, EPD_POW on
    P2SEL = SWUART_RXD ;    //Timer function for RXD pins
    P2DIR = 0xFF & ~SWUART_RXD & ~EPD_BUSY & ~BP_CS;
    //P2REN = SWUART_RXD;
    
    P2IE = 0;
    P2IFG = 0;
    P2IES |= SWUART_RXD | TIMER_1S; //P2.0 interrupt for 1s trigger
    

    P3OUT = EPD_CS | FLASH_CS;               // EPD_POW off
    P3SEL = SWUART_TXD;               // //Timer function for TXD pins
    P3DIR = 0xFF;               // Set all pins to output

}


static void draw_dec(uint8_t x, uint8_t y, uint8_t xsize, uint8_t ysize, uint8_t interval, uint8_t count, uint8_t const *pNumBase, uint16_t Num)
{
    uint8_t signum;
    uint16_t datlen;
    if (!count) return;

    datlen = ((xsize+7)>>3) * ysize;
    count--;
    y += (ysize + interval) * (count);
    do
    {
        signum = Num % 10;
        Num = Num / 10;
        EPD_DrawPic(x, y, xsize, ysize, pNumBase + datlen * signum);
        y -= ysize + interval;
    }while(count--);
}

void clock_disp_start(t_clock_disp_update *d, uint8_t mode)
{
    if (d->sta != 0xFF)
    {
        return;
    }
    d->sta = 0;
    d->mode = mode;
    LPM3Prohibit |= LPM3P_DISP;
}

extern const unsigned char acjntm_0_compressed[];
extern const unsigned char acjntm_1_compressed[];
extern const unsigned char acjntm_2_compressed[];
extern const unsigned char acjntm_3_compressed[];

const uint8_t * const c_JNTM_TAB[4] = {acjntm_0_compressed, acjntm_1_compressed, acjntm_2_compressed, acjntm_3_compressed};

void clock_disp_update(t_clock_disp_update *d)
{
    static uint8_t y_pos = 0, idx = 0; 
    static uint16_t fps_tick = 0, fps = 0;
    uint16_t tick;
    switch (d->sta)
    {
        case 0:
            EPD_InitStart(&m_EPD_InitUpdate);
            d->sta++;
        case 1:
            if (m_EPD_InitUpdate.sta != 0xFF) return;
            EPD_Clear(0);
            EPD_Disp(EPD_FULL);
            d->sta++;
            
        case 2: 
            if (EPD_BUSY_GET()) return;

            
            
            EPD_DrawPic_Compressed(0,0,128, 250, c_JNTM_TAB[idx++]);

            if (idx >= 4)
            {
                idx = 0;
                tick = g_SYSTICK;
                if (fps_tick != 0)
                {
                    fps = 4 * 1000 / (tick - fps_tick);
                }
                fps_tick = tick;
            }

            if (fps)
            {
                EPD_DrawPic(0,206,8,5, nAsciiDot5x8['F' - ' ']);
                EPD_DrawPic(0,212,8,5, nAsciiDot5x8['P' -' ']);
                EPD_DrawPic(0,218,8,5, nAsciiDot5x8['S' -' ']);
                EPD_DrawPic(0,224,8,5, nAsciiDot5x8[':' -' ']);
                draw_dec(0, 230, 16, 8, 0, 2, Font8x16[0], fps);
            }
            
            

            // EPD_Fill(48, y_pos, 16, 16, 0xFF);
            // test_tick = g_SYSTICK;

            // EPD_Disp(EPD_PART);
            EPD_Disp_Fast();

            d->sta++;
        case 3:
            if (EPD_BUSY_GET()) return;

            y_pos++;
            if (y_pos >= (250 - 16))
            {
                y_pos = 0;
            }
            d->sta = 2;
            return;

        default:
            return;
    }
}


#pragma vector = PORT2_VECTOR
__interrupt void port2_isr(void)
{
    if (P2IFG & SWUART_RXD)
    {
        P2IE &= ~SWUART_RXD;
        P2SEL |= SWUART_RXD;
        //keep the flag. handle it in shell module

        LPM3_EXIT;
    }
    if (P2IFG & TIMER_1S)
    {
        P2IFG &= ~TIMER_1S;
        g_SYSSEC++;
        
        LPM3_EXIT;
    }
}
